# Copyright (c) 2018 Presto Labs Pte. Ltd.
# Author: chensili

import logging
import time
import traceback
import typing

import coin.support.accounting.logic.estimate_util as estimate_util
import coin.proto.coin_request_pb2 as cr_pb2
from coin.support.accounting.logic.constants import TICKER_CANDIDATES_MEA
from coin.proto.coin_query_pb2 import (
    AccountBalanceEstimate,
    EstimateValue)
from coin.proto.coin_request_pb2 import AccountRequestProto
from xunkemgmt_client.support.accounting.database.db_output import DBOutputEstimate
from xunkemgmt_client.client.api_client import XunkemgmtClient
from xunkemgmt_client.support.accounting.logic.constants import (
    ACCOUNTING_CURRENCY_CANDIDATES)


def generate_balance_estimate_history_result(
      request_list: typing.List[AccountRequestProto], account_info_querier):
  response_list = []
  balance_list = account_info_querier.query_account_balance_history(request_list)
  ticker_reqs = [cr_pb2.ExchangeApiRequestProto(
        market_type=elem[0], exchange=elem[1], api_version=elem[2])
        for elem in TICKER_CANDIDATES_MEA]
  ticker_rsps = []
  with XunkemgmtClient() as client:
    for req in ticker_reqs:
      try:
        rsp = client.query_exchange_tickers(req)
        ticker_rsps.append(rsp)
      except Exception:
        logging.error(traceback.format_exc())

  assert len(request_list) == len(balance_list), (len(request_list), len(balance_list))
  for request, db_output in zip(request_list, balance_list):
    result = None
    query_time = time.time()
    try:
      account_id = request.account_id
      balance = db_output.balance
      acct_total_value = acct_total_value_in_usd = None
      accounting_currency = ACCOUNTING_CURRENCY_CANDIDATES[
          (request.market_type, request.exchange)][0]
      account_request = AccountRequestProto(
          market_type=request.market_type,
          exchange=request.exchange,
          owner=request.owner)
      estimate_detail = []
      assert isinstance(account_id, int), account_id
      for each_balance in balance.each_balance:
        each_estimate_value = estimate_util.calculate_asset_value(
              account_request, each_balance, ticker_rsps, accounting_currency)
        if acct_total_value is None:
          acct_total_value = each_estimate_value.total_value
        else:
          acct_total_value += each_estimate_value.total_value
        if each_estimate_value.total_value_in_usd is not None:
          if acct_total_value_in_usd is None:
            acct_total_value_in_usd = each_estimate_value.total_value_in_usd
          else:
            acct_total_value_in_usd += each_estimate_value.total_value_in_usd
        each_estimate_value.symbol = each_balance.currency
        each_estimate_value.accounting_currency = accounting_currency
        estimate_detail.append(each_estimate_value)
      estimate_value = EstimateValue(
          accounting_currency=accounting_currency,
          total_value=acct_total_value,
          total_value_in_usd=acct_total_value_in_usd)
      balance_estimate = AccountBalanceEstimate(
          account_request=account_request,
          query_ts=int(query_time * 10**9),
          balance=balance,
          each_ticker=ticker_rsps,
          estimate=estimate_value,
          estimate_detail=estimate_detail)
      result = DBOutputEstimate(account_id=account_id,
                                query_timestamp=query_time,
                                balance_estimate=balance_estimate,
                                balance_hid=db_output.balance_hid)
    except Exception as e:
      logging.error('Fail to generate balance estimate.', request)
      logging.error(traceback.format_exc())
    finally:
      response_list.append(result)
  assert len(request_list) == len(response_list)
  return response_list
